package com.starsea.book.ui.main.bookshelf.style1.books

import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Bundle
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.core.view.isGone
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.starsea.book.R
import com.starsea.book.base.BaseFragment
import com.starsea.book.constant.AppLog
import com.starsea.book.constant.EventBus
import com.starsea.book.data.appDb
import com.starsea.book.data.entities.Book
import com.starsea.book.data.entities.BookGroup
import com.starsea.book.databinding.DialogBookshelfConfigBinding
import com.starsea.book.databinding.FragmentBooksBinding
import com.starsea.book.help.book.isLocal
import com.starsea.book.help.config.AppConfig
import com.starsea.book.lib.dialogs.alert
import com.starsea.book.lib.theme.accentColor
import com.starsea.book.lib.theme.primaryColor
import com.starsea.book.ui.book.import.local.ImportBookActivity
import com.starsea.book.ui.book.read.ReadBookActivity
import com.starsea.book.ui.book.search.SearchActivity
import com.starsea.book.ui.main.MainViewModel
import com.starsea.book.ui.newpage.LoginActivity
import com.starsea.book.ui.newpage.ReadHistoryActivity
import com.starsea.book.ui.newpage.entity.BookShelfEntity
import com.starsea.book.ui.newpage.viewmodel.BookShelfDataState
import com.starsea.book.utils.*
import com.starsea.book.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlin.math.max

/**
 * 书架界面
 */
class BooksFragment() : BaseFragment(R.layout.fragment_books),
    BaseBooksAdapter.CallBack {

    var show: BasePopupView? = null

    var isCanIn = false

    open fun showLoading(
        message: String = "请求网络中...",
        dismissOnBack: Boolean = true,
        dismissOnTouchOut: Boolean = false
    ) {
        show = XPopup.Builder(requireContext())
            .isDestroyOnDismiss(true)
            .dismissOnBackPressed(dismissOnBack)
            .dismissOnTouchOutside(dismissOnTouchOut)
            .asLoading(message)
        show!!.show()
    }

    open fun dismissLoading() {
        show?.dismiss()
    }

    constructor(position: Int, group: BookGroup) : this() {
        val bundle = Bundle()
        bundle.putInt("position", position)
        bundle.putLong("groupId", group.groupId)
        bundle.putInt("bookSort", group.getRealBookSort())
        bundle.putBoolean("enableRefresh", group.enableRefresh)
        arguments = bundle
    }

    constructor(type: Int, entity: BookShelfEntity) : this() {
        val bundle = Bundle()
        bundle.putInt("type", type)
        bundle.putSerializable("entity", entity)
        arguments = bundle
    }

    private val binding by viewBinding(FragmentBooksBinding::bind)
    private val activityViewModel by viewModels<MainViewModel>()
    private val bookshelfLayout by lazy { AppConfig.bookshelfLayout }

    private val booksAdapter: BaseBooksAdapter<*> by lazy {
        if (bookshelfLayout == 0) {
            BooksAdapterList(requireContext(), this)
        } else {
            BooksAdapterGrid(requireContext(), this)
        }
    }
    private var booksFlowJob: Job? = null
    private var savedInstanceState: Bundle? = null
    var position = 0
        private set
    var groupId = -1L
        private set
    var bookSort = 0
        private set
    private var upLastUpdateTimeJob: Job? = null
    private var defaultScrollBarSize = 0

    var isManage = false
    override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
        setSupportToolbar(binding.titleBar.toolbar)
        binding.titleBar.toolbar.setBackgroundColor(Color.TRANSPARENT)

        this.savedInstanceState = savedInstanceState
        arguments?.let {
            position = it.getInt("position", 0)
            groupId = it.getLong("groupId", -1)
            bookSort = it.getInt("bookSort", 0)
        }

        initRecyclerView()
        upRecyclerData()

        activityViewModel.bookShelfDataState.observe(this) {

            when (it) {
                is BookShelfDataState.Success -> {
                    if (it.netData.status == 200) {

                        if (it.netData.data != null) {

                            binding.tvEmptyMsg.isGone = true

                            val listResult: MutableList<BookShelfEntity> = arrayListOf()

                            listResult.addAll(it.local)

                            it.netData.data!!.forEach {
                                listResult.addAll(it.bookShelfBooKDetailOutList)
                            }

                            LogUtils.e(">>>>>>> ", "" + it.netData.data!!.toString())

                            binding.tvEmptyMsg.isGone =
                                it.netData.data!!.isNotEmpty() || it.local.isNotEmpty()

                            booksAdapter.setItems(listResult)

                        } else {
                            binding.tvEmptyMsg.isGone = false
                        }
                    } else if (it.netData.status == 401) {

                        toastOnUi("登录过期,请重新登录")
                        LoginActivity.start(requireContext())
                    } else {

                        booksAdapter.setItems(it.local)
                        toastOnUi(it.netData.msg)
                    }
                }
            }


        }


        /*activityViewModel.bookselfListResult.observe(this) {
            if (it.status == 200) {

            } else if (it.status == 401) {
                toastOnUi("登录过期,请重新登录")
                LoginActivity.start(requireContext())
            } else {
                binding.tvEmptyMsg.gone(!it.data.isNullOrEmpty())

            }
        }*/

        activityViewModel.bookData.observe(this) {
            LogUtils.e(">>> ", "activityViewModel.bookData")
            if (!isCanIn) {
                return@observe
            }
            activityViewModel.saveBook(activityViewModel.bookData.value) {
                isCanIn = false
                startActivity<ReadBookActivity> {
                    putExtra("bookUrl", it.bookUrl)
                    putExtra("inBookshelf", true)
                }
            }
        }

        activityViewModel.bookInfoResult.observe(this) {
            if (it.status != 200) {
                toastOnUi(it.msg)
            }
        }

        binding.rtvDelete.setOnClickListener {

            var isSelLocal = false
            booksAdapter.getItems().forEach {
                if (!isSelLocal)
                    isSelLocal = it.book != null && it.book!!.isLocal && it.isSel
            }
            if (isSelLocal) {

                XPopup.Builder(requireContext())
                    .asConfirm(
                        "移出书架",
                        "是否确认移出书架？",
                        "取消",
                        "确认",
                        {
                            booksAdapter.getItems().forEach {
                                if (it.book != null && it.book!!.isLocal && it.isSel) {

                                    showLoading()
                                    activityViewModel.delLocalBook(it.book!!, false) {
                                        binding.refreshLayout.isRefreshing = false
                                        upRecyclerData()

                                        binding.rtvDelete.text = "删除"
                                        dismissLoading()
                                    }
                                }
                            }

                        },
                        {

                        },
                        false
                    ).show()
            } else {

                val bookId: MutableList<String> = arrayListOf()
                booksAdapter.getItems().forEach {
                    if (TextUtils.isEmpty(it.favorTagName))
                        if (it.book != null && !it.book!!.isLocal && it.isSel) {
                            bookId.add(it.book!!.bookUrl)
                        } else {
                            if (it.isSel) {
//                                bookId.add(
//                                    it.bookShelfBooKDetailOutList?.first()?.bookShelfId ?: ""
//                                )
                            }
                        }
                }

                if (bookId.isEmpty()) {
                    toastOnUi("请选择需要移出书架的书籍")
                    return@setOnClickListener
                }
                val ids = bookId.joinToString(",")

                LogUtils.e(">>>> ", "ids = " + ids)
                showLoading()
                activityViewModel.deleteNetBookShelf(ids)

            }

        }

        activityViewModel.deleteBookselfResult.observe(this) {
            dismissLoading()
            if (it.status == 200) {
                binding.rtvDelete.text = "删除"
                toastOnUi("删除成功")
                binding.refreshLayout.isRefreshing = false

                exitManage()
                upRecyclerData()
            } else if (it.status == 401) {
                toastOnUi("登录过期,请重新登录")
                LoginActivity.start(requireContext())
            } else {
                binding.tvEmptyMsg.gone(!it.data.isNullOrEmpty())

            }
        }


    }

    override fun onCompatCreateOptionsMenu(menu: Menu) {
        menuInflater.inflate(R.menu.main_bookshelf, menu)
        gridMenuItem = menu.findItem(R.id.menu_bookshelf_grid)
        listMenuItem = menu.findItem(R.id.menu_bookshelf_list)
        menu_exit = menu.findItem(R.id.menu_exit)
        if (AppConfig.bookshelfLayout == 0) {
            gridMenuItem!!.setVisible(true)
            listMenuItem!!.setVisible(false)
        } else {
            gridMenuItem!!.setVisible(false)
            listMenuItem!!.setVisible(true)
        }
        menu_exit!!.setVisible(isManage)
    }

    var gridMenuItem: MenuItem? = null
    var menu_exit: MenuItem? = null
    var listMenuItem: MenuItem? = null

    override fun onCompatOptionsItemSelected(item: MenuItem) {
        super.onCompatOptionsItemSelected(item)
        when (item.itemId) {
            R.id.menu_readhistory -> startActivity<ReadHistoryActivity>()
            R.id.menu_search -> startActivity<SearchActivity>()
//            R.id.menu_bookshelf_layout -> configBookshelf()
            R.id.menu_bookshelf_grid -> {
                AppConfig.bookshelfLayout = 1
                postEvent(EventBus.RECREATE, "")
                gridMenuItem!!.setVisible(false)
                listMenuItem!!.setVisible(true)
                exitManage()
            }

            R.id.menu_bookshelf_list -> {
                AppConfig.bookshelfLayout = 0
                postEvent(EventBus.RECREATE, "")
                gridMenuItem!!.setVisible(true)
                listMenuItem!!.setVisible(false)
                exitManage()
            }

            R.id.menu_add_local -> {
                startActivity<ImportBookActivity>()
            }

            R.id.menu_exit -> {
                exitManage()
            }

            R.id.menu_edit -> {
                booksAdapter.isManage = true
                booksAdapter.notifyDataSetChanged()
                isManage = true
                menu_exit!!.setVisible(true)
                binding.llManageShelf.visible()
            }
        }
    }

    fun exitManage() {

        booksAdapter.getItems().forEach {
            it.isSel = false
        }
        isManage = false
        menu_exit!!.setVisible(false)
        binding.llManageShelf.gone()
        booksAdapter.isManage = false
        booksAdapter.notifyDataSetChanged()

    }

    private fun initRecyclerView() {
        binding.rvBookshelf.setEdgeEffectColor(primaryColor)
        defaultScrollBarSize = binding.rvBookshelf.scrollBarSize
        upFastScrollerBar()
        binding.refreshLayout.setColorSchemeColors(accentColor)
        binding.refreshLayout.setOnRefreshListener {
            binding.refreshLayout.isRefreshing = false
            upRecyclerData()
        }
        if (bookshelfLayout == 0) {
            binding.rvBookshelf.layoutManager = LinearLayoutManager(context)
        } else {
            binding.rvBookshelf.layoutManager = GridLayoutManager(context, bookshelfLayout + 2)
        }
        binding.rvBookshelf.adapter = booksAdapter
        booksAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
            override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
                val layoutManager = binding.rvBookshelf.layoutManager
                if (positionStart == 0 && layoutManager is LinearLayoutManager) {
                    val scrollTo = layoutManager.findFirstVisibleItemPosition() - itemCount
                    binding.rvBookshelf.scrollToPosition(max(0, scrollTo))
                }
            }

            override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
                val layoutManager = binding.rvBookshelf.layoutManager
                if (toPosition == 0 && layoutManager is LinearLayoutManager) {
                    val scrollTo = layoutManager.findFirstVisibleItemPosition() - itemCount
                    binding.rvBookshelf.scrollToPosition(max(0, scrollTo))
                }
            }
        })
        startLastUpdateTimeJob()
    }

    private fun upFastScrollerBar() {
        val showBookshelfFastScroller = AppConfig.showBookshelfFastScroller
        binding.rvBookshelf.setFastScrollEnabled(showBookshelfFastScroller)
        if (showBookshelfFastScroller) {
            binding.rvBookshelf.scrollBarSize = 0
        } else {
            binding.rvBookshelf.scrollBarSize = defaultScrollBarSize
        }
    }

    fun upBookSort(sort: Int) {
        binding.root.post {
            arguments?.putInt("bookSort", sort)
            bookSort = sort
            upRecyclerData()
        }
    }

    fun setEnableRefresh(enableRefresh: Boolean) {
//        binding.refreshLayout.isEnabled = enableRefresh
    }

    /**
     * 更新书籍列表信息
     */
    private fun upRecyclerData() {
//        activityViewModel.bookselfList()
        booksFlowJob?.cancel()
        booksFlowJob = lifecycleScope.launch {
            appDb.bookDao.flowByGroup(BookGroup.IdLocal).map { list ->

                LogUtils.e(">>>> ", ">>>> booksData = " + list.toString())
                //排序
                when (bookSort) {
                    1 -> list.sortedByDescending { it.latestChapterTime }
                    2 -> list.sortedWith { o1, o2 ->
                        o1.name.cnCompare(o2.name)
                    }

                    3 -> list.sortedBy { it.order }

                    // 综合排序 issue #3192
                    4 -> list.sortedByDescending {
                        max(it.latestChapterTime, it.durChapterTime)
                    }

                    else -> list.sortedByDescending { it.durChapterTime }
                }
            }.flowOn(Dispatchers.Default).catch {
                AppLog.put("书架更新出错", it)
            }.conflate().collect { list ->

//                binding.refreshLayout.run {
//                    isEnabled = isEnabled && list.isNotEmpty()
//                }

                LogUtils.e(">>> ", "list = " + list.toString())

                val listShelf: MutableList<BookShelfEntity> = arrayListOf()
                list.forEach {
                    val shelf = BookShelfEntity()
                    shelf.book = it
                    shelf.isLocal = true
                    listShelf.add(shelf)
                }

//                if (listShelf.isNotEmpty())
//                booksAdapter.setItems(listShelf)
                activityViewModel.getNetBookShelf(listShelf)
                recoverPositionState()
                delay(100)
            }
        }


    }

    private fun recoverPositionState() {
        // 恢复书架位置状态
        if (savedInstanceState?.getBoolean("needRecoverState") == true) {
            val layoutManager = binding.rvBookshelf.layoutManager
            if (layoutManager is LinearLayoutManager) {
                val leavePosition = savedInstanceState!!.getInt("leavePosition")
                val leaveOffset = savedInstanceState!!.getInt("leaveOffset")
                layoutManager.scrollToPositionWithOffset(leavePosition, leaveOffset)
            }
            savedInstanceState!!.putBoolean("needRecoverState", false)
        }
    }

    override fun onPause() {
        super.onPause()
        upLastUpdateTimeJob?.cancel()
        booksFlowJob?.cancel()
    }

    override fun onResume() {
        super.onResume()
        startLastUpdateTimeJob()
        upRecyclerData()
    }

    private fun startLastUpdateTimeJob() {
        upLastUpdateTimeJob?.cancel()
        if (!AppConfig.showLastUpdateTime) {
            return
        }
        upLastUpdateTimeJob = lifecycleScope.launch {
            while (isActive) {
                if (SystemUtils.isScreenOn()) {
                    booksAdapter.upLastUpdateTime()
                }
                delay(30 * 1000)
            }
        }
    }

    fun getBooks(): List<Book> {
//        return booksAdapter.getItems()
        return arrayListOf()
    }

    fun gotoTop() {
        if (AppConfig.isEInkMode) {
            binding.rvBookshelf.scrollToPosition(0)
        } else {
            binding.rvBookshelf.smoothScrollToPosition(0)
        }
    }

    fun getBooksCount(): Int {
        return booksAdapter.itemCount
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        // 保存书架位置状态
        val layoutManager = binding.rvBookshelf.layoutManager
        if (layoutManager is LinearLayoutManager) {
            val itemPosition = layoutManager.findFirstVisibleItemPosition()
            val currentView = layoutManager.findViewByPosition(itemPosition)
            val viewOffset = currentView?.top
            if (viewOffset != null) {
                outState.putInt("leavePosition", itemPosition)
                outState.putInt("leaveOffset", viewOffset)
                outState.putBoolean("needRecoverState", true)
            } else if (savedInstanceState != null) {
                val leavePosition = savedInstanceState!!.getInt("leavePosition")
                val leaveOffset = savedInstanceState!!.getInt("leaveOffset")
                outState.putInt("leavePosition", leavePosition)
                outState.putInt("leaveOffset", leaveOffset)
                outState.putBoolean("needRecoverState", true)
            }
        }
    }

    override fun open(bookUrl: String, position: Int) {

        LogUtils.e(">>> ", ".>>> isManage = " + isManage)
        if (isManage) {

            var isSelLocal = false
            booksAdapter.getItems().forEach {
                if (it.book != null) {
                    if (it.book!!.isLocal) {
                        if (it.isSel) {
                            isSelLocal = true
                        }
                    }
                }
            }

            if (isSelLocal) {
                toastOnUi("本地书架不可和网络书架一起编辑")
                return
            }


            booksAdapter.getItem(position)!!.isSel = !booksAdapter.getItem(position)!!.isSel
            booksAdapter.notifyItemChanged(position)

            var index = 0
            booksAdapter.getItems().forEach {
                if (it.isSel) {
                    index += 1
                }
            }

            binding.rtvDelete.text = "删除（${index}）"

            return
        }

        isCanIn = true
        activityViewModel.getBookInfo(bookUrl)
    }

    override fun openBookInfo(bookUrl: String, position: Int) {
        booksAdapter.isManage = true
        booksAdapter.notifyDataSetChanged()
        isManage = true
        menu_exit!!.setVisible(true)
        binding.llManageShelf.visible()
    }

    override fun openLocal(book: String, position: Int) {
        if (isManage) {
            var isSelLocal = false
            booksAdapter.getItems().forEach {
                if (it.book != null) {
                    if (!it.book!!.isLocal) {
                        if (it.isSel) {
                            isSelLocal = true
                        }
                    }
                } else {
                    if (it.isSel) {
                        isSelLocal = true
                    }
                }
            }

            if (isSelLocal) {
                toastOnUi("本地书架不可和网络书架一起编辑")
                return
            }

            booksAdapter.getItem(position)!!.isSel = !booksAdapter.getItem(position)!!.isSel
            booksAdapter.notifyItemChanged(position)

            var index = 0
            booksAdapter.getItems().forEach {
                if (it.isSel) {
                    index += 1
                }
            }

            binding.rtvDelete.text = "删除（${index}）"

            return
        }
        startActivity<ReadBookActivity> {
            LogUtils.e(">>>>>> ", "bookUrl = " + book)
            putExtra("bookUrl", book)
        }
    }


    override fun isUpdate(bookUrl: String): Boolean {
        return activityViewModel.isUpdate(bookUrl)
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun observeLiveBus() {
        super.observeLiveBus()
        observeEvent<String>(EventBus.UP_BOOKSHELF) {
            booksAdapter.notification(it)
        }
        observeEvent<String>(EventBus.BOOKSHELF_REFRESH) {
            booksAdapter.notifyDataSetChanged()
            startLastUpdateTimeJob()
            upFastScrollerBar()
        }
    }


    @SuppressLint("InflateParams")
    fun configBookshelf() {
        alert(titleResource = R.string.bookshelf_layout) {
            val bookshelfLayout = AppConfig.bookshelfLayout
            val bookshelfSort = AppConfig.bookshelfSort
            val alertBinding =
                DialogBookshelfConfigBinding.inflate(layoutInflater)
                    .apply {
                        spGroupStyle.setSelection(AppConfig.bookGroupStyle)
                        swShowUnread.isChecked = AppConfig.showUnread
                        swShowLastUpdateTime.isChecked = AppConfig.showLastUpdateTime
                        swShowWaitUpBooks.isChecked = AppConfig.showWaitUpCount
                        swShowBookshelfFastScroller.isChecked = AppConfig.showBookshelfFastScroller
                        rgLayout.checkByIndex(bookshelfLayout)
                        rgSort.checkByIndex(bookshelfSort)
                    }
            customView { alertBinding.root }
            okButton {
                alertBinding.apply {
                    if (AppConfig.bookGroupStyle != spGroupStyle.selectedItemPosition) {
                        AppConfig.bookGroupStyle = spGroupStyle.selectedItemPosition
                        postEvent(EventBus.NOTIFY_MAIN, false)
                    }
                    if (AppConfig.showUnread != swShowUnread.isChecked) {
                        AppConfig.showUnread = swShowUnread.isChecked
                        postEvent(EventBus.BOOKSHELF_REFRESH, "")
                    }
                    if (AppConfig.showLastUpdateTime != swShowLastUpdateTime.isChecked) {
                        AppConfig.showLastUpdateTime = swShowLastUpdateTime.isChecked
                        postEvent(EventBus.BOOKSHELF_REFRESH, "")
                    }
                    if (AppConfig.showWaitUpCount != swShowWaitUpBooks.isChecked) {
                        AppConfig.showWaitUpCount = swShowWaitUpBooks.isChecked
                        activityViewModel.postUpBooksLiveData(true)
                    }
                    if (AppConfig.showBookshelfFastScroller != swShowBookshelfFastScroller.isChecked) {
                        AppConfig.showBookshelfFastScroller = swShowBookshelfFastScroller.isChecked
                        postEvent(EventBus.BOOKSHELF_REFRESH, "")
                    }

                    if (bookshelfLayout != rgLayout.getCheckedIndex()) {
                        AppConfig.bookshelfLayout = rgLayout.getCheckedIndex()
                        postEvent(EventBus.RECREATE, "")
                    }
                }
            }
            cancelButton()
        }
    }

}
